package com.spzx.product.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.api.domain.vo.SkuLockVo;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.SkuStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品sku库存表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-10-26
 */
@Service
public class SkuStockServiceImpl extends ServiceImpl<SkuStockMapper, SkuStock> implements SkuStockService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public String checkAndLock(String orderNo, List<SkuLockVo> skuLockVoList) {
        //锁库存的业务不能重复调用，因此需要防止重复请求
        String key = "sku:checkAndLock:" + orderNo; //判断是否重复请求

        //防止重复请求
        //第一次执行返回true
        boolean isFirst = redisTemplate.opsForValue().setIfAbsent(key, orderNo, 1, TimeUnit.HOURS);
        if (!isFirst) {//不是第一次执行
            return "重复提交";
        }

        // 遍历所有商品，验库存并锁库存
        skuLockVoList.forEach(skuLockVo -> {
            // 验库存：查询，返回是当前sku的库存信息
            SkuStock skuStock = baseMapper.check(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
            // 如果是null，这里就验库存失败
            if (null == skuStock) {
                skuLockVo.setHaveStock(false);//没有足够库存
            } else {
                skuLockVo.setHaveStock(true);//有足够库存
            }
        });

        // 只要有一个商品库存不足
        if (skuLockVoList.stream().anyMatch(skuLockVo -> !skuLockVo.isHaveStock())) {

            // 过滤出所有库存不足的商品
            List<SkuLockVo> noHaveStockSkuLockVoList = skuLockVoList
                    .stream()
                    .filter(item -> !item.isHaveStock())
                    .collect(Collectors.toList());

            // 拼接提示信息
            StringBuffer result = new StringBuffer();
            for(SkuLockVo noHaveStockSkuLockVo : noHaveStockSkuLockVoList) {
                result.append("商品: " + noHaveStockSkuLockVo.getSkuId() + " 库存不足; ");
            }

            //锁定失败，删除key
            redisTemplate.delete(key);

            // 响应锁定状态
            return result.toString();

        } else {//所有商品库存充足

            for (SkuLockVo skuLockVo : skuLockVoList) {
                //锁定库存
                baseMapper.lock(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
            }
        }

        // 如果所有商品都锁定成功的情况下，需要缓存锁定信息到redis。以方便将来解锁库存 或者 减库存
        String dataKey = "sku:lock:data:" + orderNo;
        this.redisTemplate.opsForValue().set(dataKey, skuLockVoList);
        return "";
    }
}
